/*
 * Copyright (c) 2000-2017 wanglei. All rights reserved.
 * TeamDev PROPRIETARY and CONFIDENTIAL.
 * Use is subject to license terms.
 */

package com.wlit.ui;

import com.wlit.JavaBrowserApplication;
import com.wlit.ui.resources.Resources;
import org.cef.CefClient;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefFrame;
import org.cef.handler.CefFocusHandlerAdapter;
import org.cef.handler.CefLoadHandlerAdapter;
import org.cef.network.CefRequest;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * @author wanglei.
 */
public class ToolBar extends JPanel {
    private static final String RUN_JAVASCRIPT = "Run JavaScript...";
    private static final String CLOSE_JAVASCRIPT = "Close JavaScript Console";
    private static final String DEFAULT_URL = "about:blank";

    private JButton backwardButton;
    private JButton forwardButton;
    private JButton refreshButton;
    private JButton stopButton;
    private JMenuItem consoleMenuItem;

    private final JTextField addressBar;

    private final CefClient client;

    private final CefBrowser browser;

    private boolean browserFocus = true;

    public ToolBar(CefClient client, CefBrowser browser) {
        this.client = client;
        this.browser = browser;
        addressBar = createAddressBar();
        setLayout(new GridBagLayout());
        add(createActionsPane(), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
                GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        add(addressBar, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 0, 4, 5), 0, 0));
        add(createMenuButton(), new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.LINE_END, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 5), 0, 0));
    }

    public void setUrl(String url) {
        addressBar.setText(url);
    }

    public void didJSConsoleClose() {
        consoleMenuItem.setText(RUN_JAVASCRIPT);
    }

    private JPanel createActionsPane() {
        backwardButton = createBackwardButton();
        forwardButton = createForwardButton();
        refreshButton = createRefreshButton();
        stopButton = createStopButton();

        JPanel actionsPanel = new JPanel();
        actionsPanel.add(backwardButton);
        actionsPanel.add(forwardButton);
        actionsPanel.add(refreshButton);
        actionsPanel.add(stopButton);
        return actionsPanel;
    }

    private JTextField createAddressBar() {
        final JTextField address = new JTextField(DEFAULT_URL);
        address.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (!browserFocus) return;
                browserFocus = false;
                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
                address.requestFocus();
            }
        });
        client.addFocusHandler(new CefFocusHandlerAdapter() {
            @Override
            public void onGotFocus(CefBrowser browser) {
                if (browserFocus) return;
                browserFocus = true;
                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
                browser.setFocus(true);
            }

            @Override
            public void onTakeFocus(CefBrowser browser, boolean next) {
                browserFocus = false;
            }
        });
        address.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //根据URL来加载网页的内容
                browser.loadURL(address.getText());
            }
        });

        client.addLoadHandler(new CefLoadHandlerAdapter() {
            @Override
            public void onLoadStart(CefBrowser browser, CefFrame frame, CefRequest.TransitionType transitionType) {
                refreshButton.setEnabled(false);
                stopButton.setEnabled(true);
            }

            @Override
            public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) {
                refreshButton.setEnabled(true);
                stopButton.setEnabled(false);
                address.setText(browser.getURL());
                backwardButton.setEnabled(browser.canGoBack());
                forwardButton.setEnabled(browser.canGoForward());
            }

            @Override
            public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, String errorText, String failedUrl) {
                stopButton.setEnabled(false);
                refreshButton.setEnabled(true);
            }
        });
        return address;
    }

    private JButton createBackwardButton() {
        return createButton("Back", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.goBack();
            }
        });
    }

    private JButton createForwardButton() {
        return createButton("Forward", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.goForward();
            }
        });
    }

    private JButton createRefreshButton() {
        return createButton("Refresh", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.reload();
            }
        });
    }

    private JButton createStopButton() {
        return createButton("Stop", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.stopLoad();
            }
        });
    }

    private JButton createButton(String caption, Action action) {
        ActionButton button = new ActionButton(caption, action);
        String imageName = caption.toLowerCase();
        button.setIcon(Resources.getIcon(imageName + ".png"));
        button.setRolloverIcon(Resources.getIcon(imageName + "-selected.png"));
        return button;
    }

    private JComponent createMenuButton() {
        final JPopupMenu popupMenu = new JPopupMenu();

        popupMenu.add(createGetHTMLMenuItem());
        popupMenu.add(createDevToolsMenuItem());
        popupMenu.add(createUploadFileMenuItem());
        popupMenu.add(createDownloadFileMenuItem());
        popupMenu.add(createJavaScriptDialogsMenuItem());
        popupMenu.add(createPDFViewerMenuItem());
        popupMenu.add(createGoogleMapsMenuItem());
        popupMenu.add(createHTML5VideoMenuItem());
        popupMenu.add(createZoomInMenuItem());
        popupMenu.add(createZoomOutMenuItem());
        popupMenu.add(createActualSizeMenuItem());
        popupMenu.add(createPrintMenuItem());
        popupMenu.add(createTianpingMenuItem());
        popupMenu.addSeparator();
        popupMenu.addSeparator();
        popupMenu.add(createAboutMenuItem());

        final ActionButton button = new ActionButton("Preferences", null);
        button.setIcon(Resources.getIcon("gear.png"));
        button.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
                    popupMenu.show(e.getComponent(), 0, button.getHeight());
                } else {
                    popupMenu.setVisible(false);
                }
            }
        });
        return button;
    }

    private Component createPrintMenuItem() {
        JMenuItem menuItem = new JMenuItem("打印");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //调用浏览器的打印功能
                browser.print();
            }
        });
        return menuItem;
    }

    private Component createTianpingMenuItem(){
        JMenuItem menuItem = new JMenuItem("天平配置");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(ToolBar.this);
//                TianpingDialog tianpingDialog = new TianpingDialog(parentFrame);
//                tianpingDialog.setVisible(true);
            }
        });
        return menuItem;
    }


    private static JCheckBoxMenuItem createCheckBoxMenuItem(String title, boolean selected, final CheckBoxMenuItemCallback action) {
        final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(title, selected);
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                action.call(menuItem.isSelected());
            }
        });
        return menuItem;
    }


    private Component createActualSizeMenuItem() {
        JMenuItem menuItem = new JMenuItem("还原");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.setZoomLevel(0.00);
            }
        });
        return menuItem;
    }

    private Component createZoomOutMenuItem() {
        JMenuItem menuItem = new JMenuItem("缩小");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                double zoom = browser.getZoomLevel();
                if (zoom > -1) {
                    browser.setZoomLevel(zoom - 0.1);
                }
            }
        });
        return menuItem;
    }

    private Component createZoomInMenuItem() {
        JMenuItem menuItem = new JMenuItem("放大");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //放大缩小功能
                double zoom = browser.getZoomLevel();
                if (zoom < 1) {
                    browser.setZoomLevel(zoom + 0.1);
                }
            }
        });
        return menuItem;
    }

    private Component createHTML5VideoMenuItem() {
        JMenuItem menuItem = new JMenuItem("天平测试");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("http://192.168.0.201/socket.html");
            }
        });
        return menuItem;
    }

    private Component createGoogleMapsMenuItem() {
        JMenuItem menuItem = new JMenuItem("Echarts演示");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("https://echarts.apache.org/examples/zh/index.html");
            }
        });
        return menuItem;
    }

    private Component createJavaScriptDialogsMenuItem() {
        JMenuItem menuItem = new JMenuItem("VUE支持");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("https://element.eleme.cn/#/zh-CN/component/switch");
            }
        });
        return menuItem;
    }

    private Component createDownloadFileMenuItem() {
        JMenuItem menuItem = new JMenuItem("下载文件测试");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("http://www.51xiazai.cn/soft/85579.htm");
            }
        });
        return menuItem;
    }

    private Component createGetHTMLMenuItem() {
        JMenuItem menuItem = new JMenuItem("获取HTML");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //查看源代码
                browser.viewSource();
            }
        });
        return menuItem;
    }


    private JMenuItem createUploadFileMenuItem() {
        JMenuItem menuItem = new JMenuItem("Upload File");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("http://www.cs.tut.fi/~jkorpela/forms/file.html#example");
            }
        });
        return menuItem;
    }

    private JMenuItem createDevToolsMenuItem() {
        JMenuItem menuItem = new JMenuItem("开发者模式");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //打开另外一个对话框
                DevToolsDialog devToolsDlg = new DevToolsDialog(JavaBrowserApplication.mainFrame, "开发者选项", browser);
                devToolsDlg.setVisible(true);
            }
        });
        return menuItem;
    }

    private JMenuItem createPDFViewerMenuItem() {
        JMenuItem menuItem = new JMenuItem("PDF预览");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browser.loadURL("http://www.orimi.com/pdf-test.pdf");
            }
        });
        return menuItem;
    }


    private JMenuItem createAboutMenuItem() {
        JMenuItem menuItem = new JMenuItem("关于我们");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(ToolBar.this);
                AboutDialog aboutDialog = new AboutDialog(parentFrame);
                aboutDialog.setVisible(true);
            }
        });
        return menuItem;
    }

    private boolean isFocusRequired() {
        String url = addressBar.getText();
        return url.isEmpty() || url.equals(DEFAULT_URL);
    }

    @Override
    public void addNotify() {
        super.addNotify();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (isFocusRequired()) {
                    addressBar.requestFocus();
                    addressBar.selectAll();
                }
            }
        });
    }

    private static class ActionButton extends JButton {
        private ActionButton(String hint, Action action) {
            super(action);
            setContentAreaFilled(false);
            setBorder(BorderFactory.createEmptyBorder());
            setBorderPainted(false);
            setRolloverEnabled(true);
            setToolTipText(hint);
            setText(null);
            setFocusable(false);
            setDefaultCapable(false);
        }
    }

    private interface CheckBoxMenuItemCallback {
        void call(boolean selected);
    }
}
